데이터 필터링
✒️ 2025-05-28 10:01 내용 수정
- Array 객체의 filter() 메소드를 사용하여 특정 조건에 맞는 데이터를 필터링하거나 제거한 결과를 새 배열에 저장할 수 있다.
- 배열#Array 객체의 메소드의 filter 참고.
- 데이터 정렬#2. flag에 따른 정렬 옵션 설정에서 사용한 함수를 변형해서 사용했다.
Array 객체의 filter() 메소드 사용
- Food.js : 데이터 중 특정 조건을 만족하는 항목들만 걸러내어 새 배열을 반환하는 함수를 추가했다.
- 필터링 기준은 칼로리, 생성 날짜를 사용했다.
- Javascript의 Date() 객체 사용 시 1월은 0, 12월은 11이며, Date 생성자에 day를 1로 주면 이전 월의 마지막 일로 생성되므로, 해당 월의 첫 날을 얻으려면 2를 넣어야 한다.
- 참고 자료 : mdn web docs Date() 생상자
/* eslint-disable */
import 'bootstrap/dist/css/bootstrap.min.css';
import '../Food.css';
import {useState} from 'react';
import FoodBox from './FoodBox.js'
import item from '../data/sample.json';
function Food() {
let [food, setFood] = useState(item);
let [flag, setFlag] = useState([true, true, true, true]);
let order = ['id', 'title', 'calorie', 'createdAt'];
let orderName = ['아이디', '이름', '칼로리', '생성날짜'];
// 필터링을 위한 함수
const calorieDown = (n) => {
let result = [...food].filter((v)=>{return (v.calorie <= n)});
setFood(result);
}
const calorieUp = (n) => {
let result = [...food].filter((v)=>{return (v.calorie >= n)});
setFood(result);
}
const dateUp = (n) => { // 날짜는 Date() 객체를 사용하여 비교했다
let dateCut = new Date(2021, n-1, 2).toISOString().substring(0, 10);
let result = [...food].filter((v)=>{
let date = new Date(v.createdAt).toISOString().substring(0, 10);
return date >= dateCut;
});
setFood(result);
}
const dateDown = (n) => {
let dateCut = new Date(2021, n-1, 2).toISOString().substring(0, 10);
let result = [...food].filter((v)=>{
let date = new Date(v.createdAt).toISOString().substring(0, 10);
return date < dateCut;
});
setFood(result);
}
const deleteItem = (id) => {
let result = [...food].filter((v)=>{return (v.id != id)});
setFood(result);
}
// 정렬을 위한 함수
let orderList = (f, i) => {
let copy = [...flag];
if (i == 1) {
if (f) {
setFood([...food].sort((a, b) => {return a[order[i]].localeCompare(b[order[i]])}));
} else {
setFood([...food].sort((a, b) => {return b[order[i]].localeCompare(a[order[i]])}));
}
} else {
if (f) {
setFood([...food].sort((a, b) => (a[order[i]] - b[order[i]])));
} else {
setFood([...food].sort((a, b) => (b[order[i]] - a[order[i]])));
}
}
copy[i] = !copy[i];
setFlag(copy);
};
return (
<>
<section className='section sec'>
<div className='container-lg'>
<h2 className='title'>Food List</h2>
<!-- 정렬 버튼들 -->
<div className='btn-wrap'>
{
order.map((el, i)=>{
return(
<button key={i} className='btn btn-primary' onClick={()=>{orderList(flag[i], i)}} >{
(flag[i]) ? orderName[i] + ' 오름차순' : orderName[i] + ' 내림차순'
} 정렬</button>
)
})
}
</div>
<!-- 필터링에 필요한 버튼들 -->
<div className='btn-wrap filter'>
<!-- 초기 배열을 다시 출력할 수 있는 버튼도 추가했다 -->
<button className='btn btn-success' onClick={()=>{setFood(item)}}>전체</button>
<!-- 필터링 버튼 -->
<button className='btn btn-success' onClick={()=>{calorieDown(200)}}>칼로리 200 이하만 보기</button>
<button className='btn btn-success' onClick={()=>{calorieUp(200)}}>칼로리 200 이상만 보기</button>
<button className='btn btn-success' onClick={()=>{dateDown(7)}}>7월 이전만 보기</button>
<button className='btn btn-success' onClick={()=>{dateUp(7)}}>7월 이후만 보기</button>
</div>
<ul className='row row-cols-1'>
{
food.map((el, i) => {
return( // 각 항목별 삭제한 배열을 반환하기 위해 항목 제거 함수를 넘겨준다
<FoodBox key={el.id} food={el} deleteItem={deleteItem}></FoodBox>
);
})
}
</ul>
</div>
</section>
</>
);
}
export default Food;
- FoodBox.js : 객체의 id 값을 이용해 filter() 함수를 적용하여 특정 항목을 제거한 새 배열을 반환한다.
function FoodBox(props) {
let {food, deleteItem} = props;
let {id, imgUrl, title, content, calorie, createdAt} = food;
let date = new Date(createdAt).toISOString().substring(0, 10);
return(
<li className='col box'>
<div className='gt'>
<img src={imgUrl} alt={title}></img>
<div className="text-box">
<ul className="info">
<li><h3>{title}</h3></li>
<li>id : {id}</li>
<li>용량 : {content}</li>
<li>칼로리 : {calorie}</li>
<li>생성 날짜 : {date}</li>
<!-- 특정 항목 제거 버튼 -->
<button className='btn btn-dark' onClick={()=>{deleteItem(id)}}>제거</button>
</ul>
</div>
</div>
</li>
)
}
export default FoodBox;
- 정렬 옵션은 데이터 정렬#2. flag에 따른 정렬 옵션 설정에서 사용하던 코드를 그대로 사용했으며, 아래줄에 각 필터링 조건별 버튼을 추가했다.
- 항목별 제거 버튼을 누르면 해당 항목을 제거한 새 배열을 반환하여 그 배열로 다시 렌더링을 한다.
- 항목을 여러 개 지우고 난 뒤에 id 기준으로 정렬하면 필터링 후에 반환된 배열에서 정렬한 결과를 보여준다.
- 필터링을 1회 거치고 난 후에 다른 필터링도 적용할 수 있지만, 범위에 해당하는 데이터가 없으면 아무 값도 나오지 않기 때문에 전체 버튼을 눌러 배열을 처음 데이터로 초기화해야 한다.
- 칼로리 200 이하의 음식만 필터링 하거나, 칼로리 200 이상의 음식만 필터링 한 결과를 칼로리 내림차순으로 정렬할 수 있다.
- 생성 날짜가 7월 이후인 경우만 필터링하거나, 7월 이전인 경우만 필터링하여 결과를 확인할 수 있다.